using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Zsa.Emulation.Memory;
using Zsa.Emulation.PPU;
using Zsa.Emulation.Games.SaveData;

namespace Zsa.Emulation.Cartridge
{
    /// <summary>
    /// A cartridge that is loaded and read to play.
    /// </summary>
    public class Cart
    {
        #region Fields
        /// <summary>
        /// The cartridge info.
        /// </summary>
        private CartridgeFileInfo _CartInfo;

        /// <summary>
        /// Stream to the cart
        /// </summary>
        private FileStream _CartStream;

        #endregion Fields
        
        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="T:Cart"/> class.
        /// </summary>
        /// <param name="cartInfo">The cart info.</param>
        internal Cart(CartridgeFileInfo cartInfo)
            : this ( cartInfo, null)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Cart"/> class.
        /// </summary>
        /// <param name="cartInfo">The cart info.</param>
        /// <param name="stream">The stream.</param>
        internal Cart(CartridgeFileInfo cartInfo, FileStream stream)
        {
            // Make sure the cart info is not null.
            if (cartInfo == null)
            {
                throw new ArgumentNullException("cartInfo", "The cart info cannot be null !");
            }
            // Make sure the rom exists.
            if (!cartInfo.RomExits)
            {
                throw new ArgumentException("The file does not exist !", "cartInfo");
            }
            // Set the member fields.
            _CartStream = stream;
            _CartInfo = cartInfo;
            
        }
        #endregion Constructor

        #region Methods
        /// <summary>
        /// Opens the cart.
        /// </summary>
        internal void OpenCart()
        {
            _CartStream =
                new FileStream(
                    _CartInfo.FullPath,
                    FileMode.Open,
                    FileAccess.Read,
                    FileShare.Read
                    );
        }

        /// <summary>
        /// Closes the cart.
        /// </summary>
        internal void CloseCart()
        {
            if (_CartStream != null)
            {
                _CartStream.Close();
            }
        }


        ///// <summary>
        ///// Resets the banks.
        ///// </summary>
        //internal void ResetBanks()
        //{
        //    _ProgramRomOne = _Mapper.PrgRomBankOne;
        //    _ProgramRomTwo = _Mapper.PrgRomBankTwo;
        //    _ChrRom = _Mapper.ChrRom;
        //}
        //private void WriteBank(MemoryBankBase bank,
        //    int offset, int count)
        //{
        //    WriteBank(bank, offset, bank.RomSize);
        //}
        ///// <summary>
        ///// Writes to the memory bank.
        ///// </summary>
        ///// <param name="bank"></param>
        ///// <param name="offset"></param>
        //private void WriteBank(MemoryBankBase bank,
        //    int offset, int count)
        //{
        //    try
        //    {
        //        byte[] _Buffer = new byte[bank.RomSize];
        //        int _Size = bank.RomSize;
        //        _CartStream.Seek(offset, SeekOrigin.Begin);
        //        int _BytesRead = _CartStream.Read(
        //            _Buffer,
        //            0,
        //            bank.RomSize
        //        );
        //        bank.InternalStream.Seek(0, SeekOrigin.Begin);
        //        bank.InternalStream.Write(_Buffer, 0, bank.RomSize);



        //        bank.InternalOffset = 0;
        //    }
        //    catch (System.Exception excep)
        //    {
        //        throw excep;
        //    }
        //}


        ///// <summary>
        ///// Reads the bank.
        ///// </summary>
        ///// <param name="buffer">The buffer.</param>
        ///// <param name="bankType">Type of the bank.</param>
        ///// <param name="bankNumber">The bank number.</param>
        //public void ReadBank(byte[] buffer,
        //    RomBankType bankType, int bankNumber)
        //{
        //    ReadBank(buffer, bankType, bankNumber, 0);
        //}

        ///// <summary>
        ///// Reads the bank.
        ///// </summary>
        ///// <param name="buffer">The buffer.</param>
        ///// <param name="bankType">Type of the bank.</param>
        ///// <param name="bankNumber">The bank number.</param>
        ///// <param name="offset">The offset.</param>
        //public virtual void ReadBank(byte[] buffer,
        //    RomBankType bankType, int bankNumber, int offset)
        //{
        //    int _OffsetSet, _Count;
        //    Stream _Stream;
        //    switch (bankType)
        //    {
        //        case RomBankType.ProgramRom:
        //            _OffsetSet = _CartInfo.PrgRomBankOffset * bankNumber;
        //            _Count = PrgRomBank.ProgramBankSize;
        //            _Stream = _ProgramRom.InternalStream;
        //            break;

        //        case RomBankType.VideoRom:
        //            _OffsetSet = _CartInfo.ChrRomBankOffset * bankNumber;
        //            _Count = ChrRomBank.CharecterRomSize;
        //            break;
        //        case RomBankType.BatteryPack:

        //            return;
        //    }
        //}


        #endregion Methods

        #region Properties

        /// <summary>
        /// Gets the file info.
        /// </summary>
        /// <value>The file info.</value>
        public CartridgeFileInfo FileInfo
        {
            get
            {
                return _CartInfo;
            }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is open.
        /// </summary>
        /// <value><c>true</c> if this instance is open; otherwise, <c>false</c>.</value>
        public bool IsOpen
        {
            get
            {
                return _CartStream != null;
            }
        }

        /// <summary>
        /// The cartridge stream.
        /// </summary>
        internal Stream CartridgeStream
        {
            get
            {
                return _CartStream;
            }
        }
        #endregion Properties



        

    }
}
